package com.spring.nio.core.startup;

import com.spring.nio.common.BasicConstant;
import com.spring.nio.core.configuration.NioServerBootstrap;
import com.spring.nio.core.event.handler.AcceptorEventHandler;
import com.spring.nio.core.event.handler.ConnectEventHandler;
import com.spring.nio.core.event.handler.ReadEventHandler;
import com.spring.nio.core.event.handler.WriteEventHandler;
import com.spring.nio.core.event.model.EventModelEnum;
import com.spring.nio.core.reactor.acceptor.AcceptorTypeEnum;
import com.spring.nio.core.reactor.acceptor.MainChatAcceptor;
import com.spring.nio.core.reactor.acceptor.MainFileAcceptor;
import com.spring.nio.core.reactor.selector.MainChatSelector;
import com.spring.nio.core.reactor.selector.MainFileSelector;
import com.spring.nio.core.reactor.selector.SelectorTypeEnum;
import com.spring.nio.core.repository.page.PaginatedListObjFactory;
import com.spring.nio.core.repository.page.PaginatedListWrapperFactory;
import com.spring.nio.core.repository.repository.MapConfiguration;
import com.spring.nio.core.server.FileSystemServer;
import com.spring.nio.util.NioUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: YSFY
 * @date: 2021-03-24 10:38
 * @pacage_name: com.spring.nio.core.startup
 * @class_name: CoreServer
 * @description: CoreServer
 */

@Slf4j
@SuppressWarnings("all")
public class CoreServer {

    /**
     * 启动核心配置服务(创建事件处理链, 创建Selector，Acceptor, springIOC容器)
     * @throws IOException
     */
    public static void startupCoreServer() throws IOException {
        NioServerBootstrap.getBootstrap()
            // 配置Selector线程
            .configSelector(SelectorTypeEnum.CHAT_SELECTOR.getName(), new MainChatSelector())
            .configSelector(SelectorTypeEnum.FILE_UPLOAD_SELECTOR.getName(), new MainFileSelector())
            .configSelector(SelectorTypeEnum.FILE_DOWNLOAD_SELECTOR.getName(), new MainFileSelector())
            // 配置Acceptor线程
            .configAcceptor(AcceptorTypeEnum.CHAT_ACCEPTOR.getName(), new MainChatAcceptor(), new InetSocketAddress(InetAddress.getByName(BasicServer.getMap().get(BasicConstant.SERVER_IP).toString()), Integer.parseInt(BasicServer.getMap().get(BasicConstant.NIO_MESSAGE_PORT).toString())))
            .configAcceptor(AcceptorTypeEnum.FILE_UPLOAD_ACCEPTOR.getName(), new MainFileAcceptor(), new InetSocketAddress(InetAddress.getByName(BasicServer.getMap().get(BasicConstant.SERVER_IP).toString()), Integer.parseInt(BasicServer.getMap().get(BasicConstant.NIO_FILE_UPLOAD_PORT).toString())))
            .configAcceptor(AcceptorTypeEnum.FILE_DOWNLOAD_ACCEPTOR.getName(), new MainFileAcceptor(), new InetSocketAddress(InetAddress.getByName(BasicServer.getMap().get(BasicConstant.SERVER_IP).toString()), Integer.parseInt(BasicServer.getMap().get(BasicConstant.NIO_FILE_DOWNLOAD_PORT).toString())))
            // 配置EventHandler
            .configEventHandler(new AcceptorEventHandler()).configEventHandler(new ReadEventHandler())
            .configEventHandler(new WriteEventHandler()).configEventHandler(new ConnectEventHandler())
            // 配置spring支持
            .configSpringIOC()
            // 配置spring事件监听
            .configEventListener()
            // 配置心跳检测线程
            .configHeatBeatThread()
            .start();

        FileSystemServer.initializeFileFolder();
    }

    /**
     * 追加额外处理：1、处理mybatis持久化SqlSessionFactory
     * @throws IOException
     */
    public static void appendHandler() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = NioServerBootstrap.getConfig().getClassPathXmlApplicationContext().getBean(SqlSessionFactoryBean.class);
        Class<?> beanType = NioServerBootstrap.getConfig().getClassPathXmlApplicationContext().getType("sqlSessionFactory");
        try {
            Field field = beanType.getDeclaredField("configuration");
            field.setAccessible(true);

            // 资源映射 @MapMethod
            MapConfiguration config = new MapConfiguration();
            // resultMap自动下划线转驼峰
            config.setMapUnderscoreToCamelCase(true);
            // 针对PaginatedList实现的Mapper返回值转换
            config.setObjectFactory(new PaginatedListObjFactory());
            config.setObjectWrapperFactory(new PaginatedListWrapperFactory());
            config.setLogImpl(StdOutImpl.class);
            sqlSessionFactoryBean.setConfiguration(config);

            field.set(sqlSessionFactoryBean, Configuration.class);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }

        // 分页拦截器 @PageQuery
        //sqlSessionFactoryBean.setPlugins(new PageInterceptor(), new IdGeneratorInterceptor(idGenerator()));
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/mappers/*.xml"));
    }
}
